import { useRef, useState } from "react";
import {Button, Image} from "antd";
import "@/components/CameraCapture/cameraCapture.scss";




/*
* Ant Design for React 关于本封装的Camera组件使用

*（1）组件是通过子传父方式传递数据，传递回来一个对象，这个对象有两个子对象，分别是base64List和fileList，使用时需要解构出来
 （2）组件有2个属性，分别是onGetCamera和onCloseCamera。其中onGetCamera是拍照和删除照片的作用，onCloseCamera是关闭摄像头的作用。
 （3）在调用的组件中，return中加载本组件
 <CameraCapture onGetCamera={getCamera}  onCloseCamera={closeCamera}/>
 javascript配合代码：

 // 设置状态参数，接收组件传递过来的数据(base64用useState,File的不用渲染，用useRef)
    const[cameraBase64List,setCameraBase64List]=useState([])
   const cameraFilesListRef=useRef([]);

//  创建一个函数，用于接收拍照的数据
const getCamera=(cameraObject)=>{
        // 每次获取摄像头模块
        setCameraBase64List(()=>[]);
         cameraFilesListRef.current=[];
        // 解构出拍照组件传递过来的两个数组，记住，名字应该与拍照组件return后的名字一摸一样
        const {base64List,fileList}=cameraObject;
        // 使用两个状态参数接收两个组件传过来的数据
        setCameraBase64List(prevState=>[...prevState,...base64List])
         cameraFilesListRef.current=fileList;
    }


//  创建一个函数，用于关闭摄像头
const closeCamera=()=>{
         cameraFilesListRef.current=[];
        setCameraBase64List(()=>[]);
    }
    *
    *
  总而言之：在调用的组件中，return放置组件，组件中有2个属性值，分别是onGetCamera和onCloseCamera，他们的值分别是
  *getCamera和closeCamera，这两个是getCamera和closeCamera的基础代码见上面。CameraFilesList其实可以用useRef接收更好

* */

export default function CameraCapture({ onGetCamera,onCloseCamera }) {
    const cameraVideoRef = useRef(null);
    const cameraCanvasRef = useRef(null);
    const [cameraStatus, setCameraStatus] = useState(false);
    const [cameraBase64List, setCameraBase64List] = useState([]);
    // const [cameraFileList, setCameraFileList] = useState([]);
    const cameraBase64ListRef = useRef([]);
    const cameraFileListRef = useRef([]);

    function successFunc(mediaStream) {
        const video = cameraVideoRef.current;
        // const video = document.getElementById('cameraVideo') as HTMLVideoElement;
        // 旧的浏览器可能没有srcObject
        if ("srcObject" in video) {
            video.srcObject = mediaStream;
        }
        video.onloadedmetadata = () => {
            video.play();
        };
    }

    function errorFunc(err) {
        console.log(`${err.name}: ${err.message}`);
        // always check for errors at the end.
    }
    // 启动摄像头
    const openMedia = () => {
        // 打开摄像头
        // 把数组存到状态值中，注意，这个要用一个回调函数操作
        // 清空cameraFileList数组元素
        // 清空状态值cameraBase64List中的元素
        // setCameraFileList(() => []);
        setCameraBase64List(() => []);

        // 摄像头拍摄参数设定
        const opt = {
            audio: false,
            video: {
                width: 1920,
                height: 1080,
                transform: "scaleX(-1)",
            },
        };
        if (navigator.mediaDevices === undefined) {
            navigator.mediaDevices = {};
        }
        navigator.mediaDevices.getUserMedia(opt).then(successFunc).catch(errorFunc);
        setCameraStatus(true);
    };

    // 关闭摄像头
    const closeMedia = () => {
        // const video = document.getElementById('cameraVideo') as HTMLVideoElement;
        const video = cameraVideoRef.current;
        const stream = video.srcObject;
        if ("getTracks" in stream) {
            const tracks = stream.getTracks();
            tracks.forEach((track) => {
                track.stop();
            });

            cameraBase64ListRef.current=[];
            cameraFileListRef.current=[];
        }
        //关闭摄像头后，cameraStatus设置为false
        setCameraStatus(false);
    };

    // 拍照片，执行一次，拍一张照片,返回Base64格式图片文件
    const takePhoto = () => {
        if (cameraStatus === false) {
            return;
        }
        // const video = document.getElementById('cameraVideo') as HTMLVideoElement;
        // const canvas = document.getElementById('cameraCanvas') as HTMLCanvasElement;
        const video = cameraVideoRef.current;
        const canvas = cameraCanvasRef.current;
        canvas.setAttribute("width", 1920);
        canvas.setAttribute("height", 1080);
        const ctx = canvas.getContext("2d");
        ctx.drawImage(video, 0, 0, video.videoWidth, video.videoHeight); // 把视频中的一帧在canvas画布里面绘制出来
        // 将图片资源转成字符串
        return canvas.toDataURL("image/jpeg");
    };
    // 把单个base64格式图片文件转换为File类型文件，接收一个base64格式图片文件
    const base64PhotoToFile = (photoBase64, fileName) => {
        // 将base64按照 , 进行分割 将前缀  与后续内容分隔开
        const data = photoBase64.split(",");
        // 利用正则表达式 从前缀中获取图片的类型信息（image/png、image/jpeg、image/webp等）
        const type = data[0].match(/:(.*?);/)[1];
        // 从图片的类型信息中 获取具体的文件格式后缀（png、jpeg、webp）
        const suffix = type.split("/")[1];
        // 使用atob()对base64数据进行解码  结果是一个文件数据流 以字符串的格式输出
        const bstr = window.atob(data[1]);
        // 获取解码结果字符串的长度
        let n = bstr.length;
        // 根据解码结果字符串的长度创建一个等长的整形数字数组
        // 但在创建时 所有元素初始值都为 0
        const u8arr = new Uint8Array(n);
        // 将整形数组的每个元素填充为解码结果字符串对应位置字符的UTF-16 编码单元
        while (n--) {
            // charCodeAt()：获取给定索引处字符对应的 UTF-16 代码单元
            u8arr[n] = bstr.charCodeAt(n);
        }
        // 利用构造函数创建File文件对象
        // new File(bits, name, options)
        // 将File文件对象返回给方法的调用者
        // 利用构造函数创建File文件对象
        // new File(bits, name, options)
        // 将File文件对象返回给方法的调用者
        // photoFileList把转换好格式的数据保存好
        return new File([u8arr], `${fileName}.${suffix}`, {
            type: type,
        });
    };

    // 获取照片，同时把每次拍照的文件处理成File格式文件，并返回数组（一个是base64格式，一个是File格式）


    const getImg = (index) => {

        // 删除照片逻辑，但为什么不激活这个

        if (index !== undefined) {
            console.log(index);

            // 从Ref中复制一份数据
            let newBase64List = cameraBase64ListRef.current.slice();
            // 根据index,删除一条数据
            newBase64List.splice(index, 1);
            cameraBase64ListRef.current = newBase64List;
            let newFileList = cameraFileListRef.current.slice();
            newFileList.splice(index, 1);
            cameraFileListRef.current = newFileList;

            setCameraBase64List([...newBase64List]);

            const base64List = cameraBase64ListRef.current.slice();
            const fileList = cameraFileListRef.current.slice();


            return {
                base64List,fileList
            };
        }

        else{
            const photoSrcList=[];
            const photoFileList=[];
            // 调动takePhoto函数，拍一个照片，这里需要这样子写
            const photoBase64=takePhoto();
            // 把摄像头拍摄到的base64类型数据存进数组
            photoSrcList.push(photoBase64);
            cameraBase64ListRef.current.push(photoBase64);
            // 把File格式文件存到数组里面
            photoFileList.push(base64PhotoToFile(photoBase64,String((new Date()).valueOf())));
            cameraFileListRef.current.push(base64PhotoToFile(photoBase64,String((new Date()).valueOf())));
            // 把数组存到状态值中，注意，这个要用一个回调函数操作

            const base64List=cameraBase64ListRef.current.slice();
            const fileList=cameraFileListRef.current.slice();
            //
            setCameraBase64List(prevState=>[...prevState,...photoSrcList]);

            return {
                base64List,fileList
            }

        }


    };

    return (
        <div>
            <div>
                {cameraStatus && (
                    <video
                        id="cameraVideo"
                        ref={cameraVideoRef}
                        style={{
                            width: "320px",
                            height: "240px",
                        }} //width,heigth试试能不能改小
                    />
                )}
                {/*这个canvas,仅仅用于转载拍照的图像，这里不显示，仅仅用于获取DOM的对象数据*/}
                <canvas
                    id="cameraCanvas"
                    ref={cameraCanvasRef}
                    style={{display: "none"}}
                />
                <div></div>
                <Button type="primary" onClick={openMedia}>
                    打开摄像头
                </Button>{" "}
                <span/>
                {cameraStatus && (
                    <Button
                        type="primary"
                        disabled={!cameraStatus}
                        onClick={() => onGetCamera(getImg())}
                    >
                        拍照
                    </Button>
                )}{" "}
                <span/>
                <Button type="primary" disabled={!cameraStatus} onClick={() => onCloseCamera(closeMedia())}>
                    关闭摄像头
                </Button>
                <hr/>
                {/*图片预览,通过cameraStatus的状态值决定是否显示图片*/}
                {/*{cameraStatus && (
                  <div className="imageDiv">
                      {(cameraBase64List || []).map((item, index) => (
                          <ImageShow
                              key={index}
                              imageSrc={item}
                              index={index}
                              onGetDeleteImageIndex={() => getImg(index)} //获取到需要删除的图片在数组的Id
                          />
                      ))}
                  </div>
              )}*/}

            </div>
            <div style={{width:1024,height:120}}>
                {cameraStatus &&  <ul className="imageShow">
                    {cameraBase64List.map((item,index)=><li key={index}>
                        <div>
                            <Image.PreviewGroup>
                                <Image src={item} width={192} height={108}/>
                            </Image.PreviewGroup>
                        </div>
                        {/*<Button color='danger' variant='filled' onClick={()=>getImg(index)}>删除图片</Button>*/}
                        <Button color='danger' variant='filled' onClick={()=>onGetCamera(getImg(index)) }>删除图片</Button>

                    </li>)}
                </ul>
                }</div>
        </div>
    );
}
